#include "stdafx.h"

#include <MyControls/TransformTool.h>
#include <MyControls/TransformEditor.h>
#include <MyControls/TransformManip.h>
#include <MyControls/App.h>

namespace My {

TransformTool::TransformTool(TransformEditor & editor) : 
	m_Editor(editor)
{
	m_Hit.code = htNone;
}

void TransformTool::Deactivate()
{
	m_Hit.code = htNone;
}

void TransformTool::OnLButtonDown(UINT nFlags, CPoint p)
{
	m_Hit = GetHitInfo(p);
}

void TransformTool::OnLButtonUp(UINT nFlags, CPoint p)
{
	m_Hit.code = htNone;
}

void TransformTool::OnMouseMove(UINT nFlags, CPoint p)
{
	switch (m_Hit.code) {
		case htMove:
			m_Editor.GetBench().SetManipulator(
				std::auto_ptr<Manipulator>(new TransformMove(m_Editor, p))
			);
			break;
		case htRotate:
			m_Editor.GetBench().SetManipulator(
				std::auto_ptr<Manipulator>(new TransformRotate(m_Editor, p))
			);
			break;
		case htCornerPin:
			m_Editor.GetBench().SetManipulator(
				std::auto_ptr<Manipulator>(new CornerPin(m_Editor, p, m_Hit.index))
			);
			break;
	}
	m_Hit.code = htNone;
	m_Hit.index = -1;
}

bool TransformTool::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	CPoint p;
	GetCursorPos(&p);
	m_Editor.GetBench().ScreenToClient(&p);
	HitInfo info = m_Hit;
	if (info.code == htNone)
		info = GetHitInfo(p);

	switch (info.code) {
		case htMove:
			SetCursor(GetApp().LoadCursor("CURSOR_EDIT"));
			return true;
		case htRotate:
			SetCursor(GetApp().LoadCursor("CURSOR_EDIT_ROTATE"));
			return true;
		case htCornerPin:
			SetCursor(GetApp().LoadCursor("CURSOR_EDIT_CROSS"));
			return true;
		default:
			return false;
	}
}


TransformTool::HitInfo TransformTool::GetHitInfo(CPoint p) const
{
	HitInfo info;
	info.code = htNone;
	info.index = -1;

	if (!m_Editor.IsOpen())
		return info;

	CPoint pp[4];
	rect<double> rBounds = m_Editor.GetTransformOwner()->GetBounds();
	const Affine & t = m_Editor.GetTransform();
	pp[0] = m_Editor.GetBench().BenchToClient(point<float>(t(point<double>(rBounds.x1, rBounds.y2))));
	pp[1] = m_Editor.GetBench().BenchToClient(point<float>(t(point<double>(rBounds.x1, rBounds.y1))));
	pp[2] = m_Editor.GetBench().BenchToClient(point<float>(t(point<double>(rBounds.x2, rBounds.y1))));
	pp[3] = m_Editor.GetBench().BenchToClient(point<float>(t(point<double>(rBounds.x2, rBounds.y2))));

	CRect r(p, p);
	r.InflateRect(3, 3);

	for (int i = 0; i < 3; ++i)
		if (r.PtInRect(pp[i])) {
			info.code = htCornerPin;
			info.index = i;
			return info;
		}

	CRgn rgn; rgn.CreatePolygonRgn(pp, 4, ALTERNATE);
	if (rgn.PtInRegion(p)) {
		info.code = htMove;
		return info;
	} else {
		info.code = htRotate;
		return info;
	}
}

} // My